#include <iostream>
#include <cstring>
#include <thread>
#include <map>
#include <fstream>
#include <mutex>
#include <list>
#include <cstdio>


extern "C"
{
    
    #include <sys/epoll.h>
    #include <unistd.h>
    #include <arpa/inet.h>  
    #include <sys/socket.h>
    #include <poll.h>
}
//回应请求协议：{choise:refuse,request:Repentance}
//注册协议：{user:username,admin:useradmin}
//登录协议：{loginuser:ussername,loginadmin:useradmin}
//创建房间协议：{room:create,choise:player}
//加入房间协议,玩家{room:join,choise:player}
//加入房间协议,玩家{room:join,choise:visited}
//房间刷新协议:{player:}

#define PORT 9999              //端口号
#define LISTEN_NUMBER 50        //监听数量
#define CONNECT_NUMBER 50      //最大连接数
#define RECEIVE_SIZE 256       //接收客户端数据大小
#define IP_SIZE 32             //存储收到IP的大小
#define DATA_SIZE 128          //存储转发的数据大小

using namespace std;
mutex ljx;//随便定义的锁名


//每个房间储存对战用户、观战用户套接字的数据和epoll实例
struct  room{
    int connefd_P1=0;
    int connefd_P2=0;
    int connefd_O1=0;
    int connefd_O2=0;
    int connefd_O3=0;
    int connefd_O4=0;
    int connefd_O5=0;  
    int room_num=0;
    int epfd=0; 
    int ready1=0;
    int ready2=0;  
    int a=0,b=0,c=0,d=0,e=0,f=0,g=0;//用来标志客户端是加入或者退出
};
//全局初始一个大厅房间链表
list<room> Da_Ting; 

struct UserInfo
{
    string name;
    string admin;
};

//设计客户端数据结构
struct ClientInfo
{
    string name;
    string admin;
    unsigned int ip;
    int sockfd;
} clientInfo[CONNECT_NUMBER];

map<string,string> userid;



class waitroom
{
private:
    char recv_buf[256];
    

public:                                                          
    //创建房间并开始监听所有成员   已内建房间新epoll   需要很多协议->（发送房主可已进入，监听逻辑，就未清楚每个room成员会接收到什么数据，又该做出什么反应)未实现
    void new_play_room()
    {
        int new_room_num=1;
        ljx.lock();

        for(int i=1;i<=100 ;++i)//查找房间链表里没有创建房间号                    
        {
            for(list<room>::iterator it = Da_Ting.begin() ; ; ++it )
            {
                if(it->room_num==i)
                {
                    new_room_num = 0;
                    break;
                }
                
                if(it == Da_Ting.end())
                break;

                new_room_num = i;
            }
            if(new_room_num!=0)
            break;
        }
        cout<<"创建"<<new_room_num<<"号房间"<<endl;
        room n_room;
        n_room.room_num = new_room_num;

        //epoll创建
        n_room.epfd = epoll_create(50);
        if(n_room.epfd < 0)
        {
            perror("epfd error");
        }

        Da_Ting.push_back(n_room);
        ljx.unlock();

        list<room>::iterator its = Da_Ting.begin();
        for( ; ; ++its )//查找新创建房间节点,若房间存在,则its指向该房间链表节点
        {
            
            if(its->room_num==n_room.room_num)
            {
                cout<<"找到"<<its->room_num<<"号房间"<<endl;
                
                break;
            } 
            
            if(its == Da_Ting.end())
            {
                cout<<"该房间不存在"<<endl;
                break;
            }
            
        }
        
        while(1)
        {
            //循环判断加入epoll
            if(its->connefd_P1!=0 && its->a==0)
            {
                //将进入房间的客户端通信套接字加入epoll监听
                cout<<"正在添加P1"<<endl;
                struct epoll_event event;
                event.events = EPOLLIN;
                event.data.fd = its->connefd_P1;
                int reval = epoll_ctl(its->epfd, EPOLL_CTL_ADD, its->connefd_P1, &event);
                if(reval < 0)
                {
                    perror("ctl_con error");
                }
                its->a=1;
            }
            // if(its->connefd_P1!=0 && its->a==1)
            // {
            //     //将进入房间的客户端通信套接字加入epoll监听
            //     cout<<"P1正在退出"<<endl;
            //     struct epoll_event event;
            //     event.events = EPOLLIN;
            //     event.data.fd = its->connefd_P1;
            //     int reval = epoll_ctl(its->epfd, EPOLL_CTL_DEL, its->connefd_P1, &event);
            //     if(reval < 0)
            //     {
            //         perror("ctl_con error");
            //     }
            //     its->a=0;
            //     ljx.lock();
            //     its->connefd_P1=0;
            //     ljx.unlock();
            // }
            if(its->connefd_P2!=0 && its->b==0)
            {
                //将进入房间的客户端通信套接字加入epoll监听
                cout<<"正在添加P2"<<endl;
                struct epoll_event event;
                event.events = EPOLLIN;
                event.data.fd = its->connefd_P2;
                int reval = epoll_ctl(its->epfd, EPOLL_CTL_ADD, its->connefd_P2, &event);
                if(reval < 0)
                {
                    perror("ctl_con error");
                }
                its->b=1;
            }
            // if(its->connefd_P2!=0 && its->b==1)
            // {
            //     //将进入房间的客户端通信套接字加入epoll监听
            //     cout<<"P2正在退出"<<endl;
            //     struct epoll_event event;
            //     event.events = EPOLLIN;
            //     event.data.fd = its->connefd_P2;
            //     int reval = epoll_ctl(its->epfd, EPOLL_CTL_DEL, its->connefd_P2, &event);
            //     if(reval < 0)
            //     {
            //         perror("ctl_con error");
            //     }
            //     its->b=0;
            //     ljx.lock();
            //     its->connefd_P2=0;
            //     ljx.unlock();
            // }
            if(its->connefd_O1!=0 && its->c==0)
            {
                //将进入房间的客户端通信套接字加入epoll监听
                cout<<"正在添加O1"<<endl;
                struct epoll_event event;
                event.events = EPOLLIN;
                event.data.fd = its->connefd_O1;
                int reval = epoll_ctl(its->epfd, EPOLL_CTL_ADD, its->connefd_O1, &event);
                if(reval < 0)
                {
                    perror("ctl_con error");
                }
                its->c=1;
            }
            // if(its->connefd_O1!=0 && its->c==1)
            // {
            //     //将进入房间的客户端通信套接字加入epoll监听
            //     cout<<"O1正在退出"<<endl;
            //     struct epoll_event event;
            //     event.events = EPOLLIN;
            //     event.data.fd = its->connefd_O1;
            //     int reval = epoll_ctl(its->epfd, EPOLL_CTL_DEL, its->connefd_O1, &event);
            //     if(reval < 0)
            //     {
            //         perror("ctl_con error");
            //     }
            //     its->c=0;
            //     ljx.lock();
            //     its->connefd_O1=0;
            //     ljx.unlock();
            // }
            if(its->connefd_O2!=0 && its->d==0)
            {
                //将进入房间的客户端通信套接字加入epoll监听
                cout<<"正在添加O2"<<endl;
                struct epoll_event event;
                event.events = EPOLLIN;
                event.data.fd = its->connefd_O2;
                int reval = epoll_ctl(its->epfd, EPOLL_CTL_ADD, its->connefd_O2, &event);
                if(reval < 0)
                {
                    perror("ctl_con error");
                }
                its->d=1;
            }
        //    if(its->connefd_O2!=0 && its->d==1)
        //     {
        //         //将进入房间的客户端通信套接字加入epoll监听
        //         cout<<"O2正在退出"<<endl;
        //         struct epoll_event event;
        //         event.events = EPOLLIN;
        //         event.data.fd = its->connefd_O2;
        //         int reval = epoll_ctl(its->epfd, EPOLL_CTL_DEL, its->connefd_O2, &event);
        //         if(reval < 0)
        //         {
        //             perror("ctl_con error");
        //         }
        //         its->d=0;
        //         ljx.lock();
        //         its->connefd_O2=0;
        //         ljx.unlock();
        //     }
            if(its->connefd_O3!=0 && its->e==0)
            {
                //将进入房间的客户端通信套接字加入epoll监听
                cout<<"正在添加O3"<<endl;
                struct epoll_event event;
                event.events = EPOLLIN;
                event.data.fd = its->connefd_O3;
                int reval = epoll_ctl(its->epfd, EPOLL_CTL_ADD, its->connefd_O3, &event);
                if(reval < 0)
                {
                    perror("ctl_con error");
                }
                its->e=1;
            }
            // if(its->connefd_O3!=0 && its->e==1)
            // {
            //     //将进入房间的客户端通信套接字加入epoll监听
            //     cout<<"O3正在退出"<<endl;
            //     struct epoll_event event;
            //     event.events = EPOLLIN;
            //     event.data.fd = its->connefd_O3;
            //     int reval = epoll_ctl(its->epfd, EPOLL_CTL_DEL, its->connefd_O3, &event);
            //     if(reval < 0)
            //     {
            //         perror("ctl_con error");
            //     }
            //     its->e=0;
            //     ljx.lock();
            //     its->connefd_O3=0;
            //     ljx.unlock();
            // }
            if(its->connefd_O4!=0 && its->f==0)
            {
                //将进入房间的客户端通信套接字加入epoll监听
                cout<<"正在添加O4"<<endl;
                struct epoll_event event;
                event.events = EPOLLIN;
                event.data.fd = its->connefd_O4;
                int reval = epoll_ctl(its->epfd, EPOLL_CTL_ADD, its->connefd_O4, &event);
                if(reval < 0)
                {
                    perror("ctl_con error");
                }
                its->f=1;
            }
            // if(its->connefd_O4!=0 && its->f==1)
            // {
            //     //将进入房间的客户端通信套接字加入epoll监听
            //     cout<<"O4正在退出"<<endl;
            //     struct epoll_event event;
            //     event.events = EPOLLIN;
            //     event.data.fd = its->connefd_O4;
            //     int reval = epoll_ctl(its->epfd, EPOLL_CTL_DEL, its->connefd_O4, &event);
            //     if(reval < 0)
            //     {
            //         perror("ctl_con error");
            //     }
            //     its->f=0;
            //     ljx.lock();
            //     its->connefd_O4=0;
            //     ljx.unlock();
            // }
            if(its->connefd_O5!=0 && its->g==0)
            {
                //将进入房间的客户端通信套接字加入epoll监听
                cout<<"正在添加05"<<endl;
                struct epoll_event event;
                event.events = EPOLLIN;
                event.data.fd = its->connefd_O5;
                int reval = epoll_ctl(its->epfd, EPOLL_CTL_ADD, its->connefd_O5, &event);
                if(reval < 0)
                {
                    perror("ctl_con error");
                }
                its->g=1;
            }
            // if(its->connefd_O5!=0 && its->g==1)
            // {
            //     //将进入房间的客户端通信套接字加入epoll监听
            //     cout<<"O5正在退出"<<endl;
            //     struct epoll_event event;
            //     event.events = EPOLLIN;
            //     event.data.fd = its->connefd_O5;
            //     int reval = epoll_ctl(its->epfd, EPOLL_CTL_DEL, its->connefd_O5, &event);
            //     if(reval < 0)
            //     {
            //         perror("ctl_con error");
            //     }
            //     its->g=0;
            //     ljx.lock();
            //     its->connefd_O5=0;
            //     ljx.unlock();
            // }

            
            


            //等待数据发生
            struct epoll_event reevent_bf[50];
            int size = epoll_wait(n_room.epfd, reevent_bf, 50, 0);
            if(size < 0)
            {
                perror("wait error");
                continue;
            }
            for(int num = 0; num < size; num++)
            {
                int reval;
                //客户端来数据
                if(reevent_bf[num].data.fd == its->connefd_P1 && reevent_bf[num].data.fd !=0)//P1房主发来讯息的响应
                {
                    reval = recv(reevent_bf[num].data.fd, recv_buf, sizeof(recv_buf), 0);
                    if(reval < 0)
                    {
                        perror("recv error");
                        close(reevent_bf[num].data.fd);
                    }
                    else if(reval == 0)
                    {
                        cout << "客户端下线\n";
                        close(reevent_bf[num].data.fd);
                    }
                    else
                    {
                        cout<<recv_buf;
                        // if(recv_buf[0]=='1')
                        // {
                        //     cout<<"shoudao:"<<recv_buf[0]<<endl;
                        // }
                        // if(recv_buf[0]=='0')
                        // {
                        //     cout<<"shoudao:"<<recv_buf[0]<<endl;
                        // }
                        // if(recv_buf[0]=='2')
                        // {
                        //     cout<<"shoudao:"<<recv_buf[0]<<endl;
                        // }
                        bzero(recv_buf, sizeof(recv_buf));

                    }
                }

                else if(reevent_bf[num].data.fd == n_room.connefd_P2&& reevent_bf[num].data.fd !=0)//P2玩家发来讯息的响应
                {
                    reval = recv(reevent_bf[num].data.fd, recv_buf, sizeof(recv_buf), 0);
                    if(reval < 0)
                    {
                        perror("recv error");
                        close(reevent_bf[num].data.fd);
                    }
                    else if(reval == 0)
                    {
                        cout << "客户端下线\n";
                        close(reevent_bf[num].data.fd);
                    }
                    else
                    {
                        cout<<recv_buf;
                        // if(recv_buf[0]=='1')
                        // {
                        //     cout<<"shoudao:"<<recv_buf[0]<<endl;
                        // }
                        // if(recv_buf[0]=='0')
                        // {
                        //     cout<<"shoudao:"<<recv_buf[0]<<endl;
                        // }
                        // if(recv_buf[0]=='2')
                        // {
                        //     cout<<"shoudao:"<<recv_buf[0]<<endl;
                        // }
                        bzero(recv_buf, sizeof(recv_buf));

                    }
                }

                else if(reevent_bf[num].data.fd == n_room.connefd_O1&& reevent_bf[num].data.fd !=0)//O1观战人发来退出观战讯息的响应
                {
                    reval = recv(reevent_bf[num].data.fd, recv_buf, sizeof(recv_buf), 0);
                    if(reval < 0)
                    {
                        perror("recv error");
                        close(reevent_bf[num].data.fd);
                    }
                    else if(reval == 0)
                    {
                        cout << "客户端下线\n";
                        close(reevent_bf[num].data.fd);
                    }
                    else
                    {

                        if(recv_buf[0]=='1')
                        {
 
                        }

                        bzero(recv_buf, sizeof(recv_buf));

                    }
                }

                else if(reevent_bf[num].data.fd == n_room.connefd_O2&& reevent_bf[num].data.fd !=0)//O2观战人发来退出观战讯息的响应
                {
                    reval = recv(reevent_bf[num].data.fd, recv_buf, sizeof(recv_buf), 0);
                    if(reval < 0)
                    {
                        perror("recv error");
                        close(reevent_bf[num].data.fd);
                    }
                    else if(reval == 0)
                    {
                        cout << "客户端下线\n";
                        close(reevent_bf[num].data.fd);
                    }
                    else
                    {

                        if(recv_buf[0]=='1')
                        {
 
                        }
            
                        bzero(recv_buf, sizeof(recv_buf));

                    }
                }

                else if(reevent_bf[num].data.fd == n_room.connefd_O3&& reevent_bf[num].data.fd !=0)//O3观战人发来退出观战讯息的响应
                {
                    reval = recv(reevent_bf[num].data.fd, recv_buf, sizeof(recv_buf), 0);
                    if(reval < 0)
                    {
                        perror("recv error");
                        close(reevent_bf[num].data.fd);
                    }
                    else if(reval == 0)
                    {
                        cout << "客户端下线\n";
                        close(reevent_bf[num].data.fd);
                    }
                    else
                    {

                        if(recv_buf[0]=='1')
                        {
 
                        }
            
                        bzero(recv_buf, sizeof(recv_buf));

                    }
                }

                else if(reevent_bf[num].data.fd == n_room.connefd_O4&& reevent_bf[num].data.fd !=0)//O2观战人发来退出观战讯息的响应
                {
                    reval = recv(reevent_bf[num].data.fd, recv_buf, sizeof(recv_buf), 0);
                    if(reval < 0)
                    {
                        perror("recv error");
                        close(reevent_bf[num].data.fd);
                    }
                    else if(reval == 0)
                    {
                        cout << "客户端下线\n";
                        close(reevent_bf[num].data.fd);
                    }
                    else
                    {

                        if(recv_buf[0]=='1')
                        {
 
                        }
            
                        bzero(recv_buf, sizeof(recv_buf));

                    }
                }

                else if(reevent_bf[num].data.fd == n_room.connefd_O5&& reevent_bf[num].data.fd !=0)//O2观战人发来退出观战讯息的响应
                {
                    reval = recv(reevent_bf[num].data.fd, recv_buf, sizeof(recv_buf), 0);
                    if(reval < 0)
                    {
                        perror("recv error");
                        close(reevent_bf[num].data.fd);
                    }
                    else if(reval == 0)
                    {
                        cout << "客户端下线\n";
                        close(reevent_bf[num].data.fd);
                    }
                    else
                    {

                        if(recv_buf[0]=='1')
                        {
 
                        }
            
                        bzero(recv_buf, sizeof(recv_buf));

                    }
                }

            }

        }





    }

    //玩家1进入房间
    static void P1_add_room(int connefd)
    {
        
        ljx.lock();
        list<room>::iterator it = Da_Ting.begin();
        for(int i=1;i<=5 ;++i)//查找房间链表里没P1的房间                    
        {
            for( ; ; ++it )
            {
                if(it->connefd_P1==0)
                {
                    break;
                }
                
                if(it == Da_Ting.end())
                {
                    cout<<"没有空房间"<<endl;
                    return;
                }
                
            }
            
            
        }
        it->connefd_P1=connefd;
 
        //将新房间的数据放房间链表里-----添加链表节点
        
        ljx.unlock();

    }

    //玩家2进入房间,进入被监听状态 - --需主线程服务器调用      需要通知 玩家 进入的协议->（未通知房主加人）
    static void P2_add_room(int connefd)
    {
        cout<<"p2 come"<<endl;
        ljx.lock();
        int membernum=0;
        char buff[36];
        list<room>::iterator its = Da_Ting.begin();               
        
            for( ; ; ++its )
            {
                
                if(its->connefd_P2==0)
                {
                    its->connefd_P2=connefd;
                    break;
                }
                
                else if(its == Da_Ting.end())
                {
                    cout<<"没有空房间"<<endl;
                    ljx.unlock();
                    return;
                }
                
            }
        
        if(its->connefd_P1!=0)
        {
            membernum++;
        }
        if(its->connefd_P2!=0)
        {
            membernum++;
        }
        if(its->connefd_O1!=0)
        {
            membernum++;
        }
        if(its->connefd_O2!=0)
        {
            membernum++;
        }
        if(its->connefd_O3!=0)
        {
            membernum++;
        }
        if(its->connefd_O4!=0)
        {
            membernum++;
        }
        if(its->connefd_O5!=0)
        {
            membernum++;
        }



        sprintf(buff,"{refresh:human,number:%d}",membernum);

        if(its->connefd_P1!=0)
        {
            send(its->connefd_P1,buff,strlen(buff)+1,0);
        }
        if(its->connefd_P2!=0)
        {
            send(its->connefd_P2,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O1!=0)
        {
            send(its->connefd_O1,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O2!=0)
        {
            send(its->connefd_O2,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O3!=0)
        {
            send(its->connefd_O3,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O4!=0)
        {
            send(its->connefd_O4,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O5!=0)
        {
            send(its->connefd_O5,buff,strlen(buff)+1,0);
        }


        ljx.unlock();


    }

    //观战人进入对局房间,进入被监听状态 ---需主线程服务器调用    需要通知客户端 观战人 进入的协议->（未通知房主加人）
    static void observer_add_room(int connefd)
    {
        cout<<"visited  come"<<endl;
        int membernum=0;
        char buff[36];
        ljx.lock();
        list<room>::iterator its = Da_Ting.begin();
        for( ; ; ++its )//查找要加入的房间节点,若房间存在,则its指向该房间链表节点
        {
            
                if(its->connefd_O1==0)
            {
                its->connefd_O1=connefd;
                cout<<"添加O1中"<<endl;
                break;
            }
            else if(its->connefd_O2==0)
            {
                its->connefd_O2=connefd;
                //将进入房间的观战客户端通信套接字加入epoll监听
                cout<<"添加O2中"<<endl;
                break;
            }
            else if(its->connefd_O3==0)
            {
                its->connefd_O3=connefd;
                cout<<"添加O3中"<<endl;
                break;
            }
            else if(its->connefd_O4==0)
            {
                its->connefd_O4=connefd;
                cout<<"添加O4中"<<endl;
                break;
            }
            else if(its->connefd_O5==0)
            {
                its->connefd_O5=connefd;
                cout<<"添加O5中"<<endl;
                break;
            }
            else if(its==Da_Ting.end())
            {
                cout<<"无位置"<<endl;
                break;
            }
        }

        
        if(its->connefd_P1!=0)
        {
            membernum++;
        }
        if(its->connefd_P2!=0)
        {
            membernum++;
        }
        if(its->connefd_O1!=0)
        {
            membernum++;
        }
        if(its->connefd_O2!=0)
        {
            membernum++;
        }
        if(its->connefd_O3!=0)
        {
            membernum++;
        }
        if(its->connefd_O4!=0)
        {
            membernum++;
        }
        if(its->connefd_O5!=0)
        {
            membernum++;
        }


        sprintf(buff,"{refresh:human,number:%d}",membernum);

        if(its->connefd_P1!=0)
        {
            send(its->connefd_P1,buff,strlen(buff)+1,0);
        }
        if(its->connefd_P2!=0)
        {
            send(its->connefd_P2,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O1!=0)
        {
            send(its->connefd_O1,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O2!=0)
        {
            send(its->connefd_O2,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O3!=0)
        {
            send(its->connefd_O3,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O4!=0)
        {
            send(its->connefd_O4,buff,strlen(buff)+1,0);
        }
        if(its->connefd_O5!=0)
        {
            send(its->connefd_O5,buff,strlen(buff)+1,0);
        }

        
        ljx.unlock();
    }

    //退出房间 ---用于epoll识别到才进行的操作    （想办法通知主线程服务器添加）未实现
    static void exit(int connefd )
    {
        ljx.lock();
        //删除观战人在房间的epoll树节点
        list<room>::iterator its = Da_Ting.begin();
        for( ; ; ++its )//查找要删除的房间节点,若房间存在,则its指向该房间链表节点   并清0观战人所在的room链表节点里的数据
        {
            if(its->connefd_P1==connefd)
            {
                its->a=1;
                break;
            }
            else if(its->connefd_P2==connefd)
            {
                its->b=1;
                break;
            }
            else if(its->connefd_O1==connefd)
            {
                its->c=1;
                break;
            }
            else if(its->connefd_O2==connefd)
            {
                its->d=1;
                break;
            }
            else if(its->connefd_O3==connefd)
            {
                its->e=1;
                break;
            }
            else if(its->connefd_O4==connefd)
            {
                its->f=1;
                break;
            }
            else if(its->connefd_O5==connefd)
            {
                its->g=1;
                break;
            } 
              
        }
        
        ljx.unlock();
   
    }

    //玩家准备函数  
    static void ready(int connefd)
    {
        list<room>::iterator its = Da_Ting.begin();
        for( ; ; ++its )
        {
            if (its->connefd_P1==connefd)
            {
                if(its->ready1==0)
                {
                    its->ready1=1;
                }
                else if(its->ready2==0)
                {
                    its->ready2=1;
                }
                break;
            }
            else if(its->connefd_P2==connefd)
            {
                if(its->ready1==0)
                {
                    its->ready1=1;
                }
                else if(its->ready2==0)
                {
                    its->ready2=1;
                }
                break;
            }
            else if(its==Da_Ting.end())
            {
                break;
            }
        }
        if(its->ready1==1)
        {
            if(its->ready2==1)
            {
                            
                if(its->connefd_P1!=0)
                {
                    send(its->connefd_P1,"{allready:yes,goto:defaut}",sizeof("{allready:yes,goto:defaut}"),0);
                }
                if(its->connefd_P2!=0)
                {
                    send(its->connefd_P2,"{allready:yes,goto:defaut}",sizeof("{allready:yes,goto:defaut}"),0);
                }
                if(its->connefd_O1!=0)
                {
                    send(its->connefd_O1,"{allready:yes,goto:defaut}",sizeof("{allready:yes,goto:defaut}"),0);
                }
                if(its->connefd_O2!=0)
                {
                    send(its->connefd_O2,"{allready:yes,goto:defaut}",sizeof("{allready:yes,goto:defaut}"),0);
                }
                if(its->connefd_O3!=0)
                {
                    send(its->connefd_O3,"{allready:yes,goto:defaut}",sizeof("{allready:yes,goto:defaut}"),0);
                }
                if(its->connefd_O4!=0)
                {
                    send(its->connefd_O4,"{allready:yes,goto:defaut}",sizeof("{allready:yes,goto:defaut}"),0);
                }
                if(its->connefd_O5!=0)
                {
                    send(its->connefd_O5,"{allready:yes,goto:defaut}",sizeof("{allready:yes,goto:defaut}"),0);
                }

            }

        }
    }

    //玩家取消准备函数
    static void unready(int connefd)
    {
        list<room>::iterator its = Da_Ting.begin();
        for( ; ; ++its )
        {
            if (its->connefd_P1==connefd)
            {
                if(its->ready1==1)
                {
                    its->ready1=0;
                }
                else if(its->ready2==1)
                {
                    its->ready2=0;
                }
                break;
            }
            else if(its->connefd_P2==connefd)
            {
                if(its->ready1==1)
                {
                    its->ready1=0;
                }
                else if(its->ready2==1)
                {
                    its->ready2=0;
                }
                break;
            }
            else if(its==Da_Ting.end())
            {
                break;
            }
        }
    }

};

void read_file(void)
{
    UserInfo userInfo;
    ifstream in("user.txt");
    if (!in.is_open())
    {
        cout << "无法读取文件" << endl;
    }

    string line;
    bool userExists = false;

    while (getline(in, line))
    {
        // 找到等号的位置
        size_t p = line.find(',');
        if (p != string::npos)
        {
            // 分割
            string first = line.substr(0, p);
            string second = line.substr(p + 1);

            // 存入映射
            userid[first] = second;
        }
    }
    in.close();
}


bool message(int sockfd, char recvbuf[256])
{
    char sendbuf[128];
    char user[36], admin[64];
    char username[36], useradmin[64];
    char usetime[32];
    char worng[128];
    int num, i;
    FILE *fp;
    time_t t ;
    struct tm *now_time;
    
    sscanf(recvbuf, "{%[^:]:%[^,],%[^:]:%[^}]}", user, username, admin, useradmin);
    if(recvbuf[0] != '{' && recvbuf[strlen(recvbuf)] != '}')
    {
        send(sockfd, "格式错误\n", sizeof("格式错误\n"), 0);
        return false;
    }
    else
    {
        
        if(strcmp(user, "user") == 0)
        {
            map<string, string> :: iterator it = userid.find(username);
            if(it != userid.end())
            {
                send(sockfd, "用户名已经存在，请重新注册\n", sizeof("用户名已经存在，请重新注册\n"), 0);
                return false;
            }
            
            ofstream out("user.txt", ios::app);
            if(out.is_open())
            {
                out << username << "," << useradmin << "\n";
                out.close();
                userid[username] = useradmin;
                sprintf(sendbuf, "注册账号成功,%s\n", username);
                send(sockfd, sendbuf, strlen(sendbuf)+1, 0);
            }
            else 
            {
                cout << "无法写入文件" << endl;
            }
        }
        else if(strcmp(user, "loginuser") == 0)
        {
            map<string, string> :: iterator it = userid.find(username);
            if(it != userid.end())
            {
                if(it->second == useradmin)
                {
                    for(num = 0; num < 50; num++)
                    {
                        if(clientInfo[num].sockfd == 0)
                        {
                            clientInfo[num].sockfd = sockfd;
                            clientInfo[num].name == username;
                            clientInfo[num].admin == useradmin;
                            //clientInfo[num].ip = addr.sin_addr.s_addr; //保存客户端地址

                            sprintf(sendbuf, "登录成功,欢迎回来，%s\n", username);
                            send(sockfd, sendbuf, strlen(sendbuf)+1, 0);
                            return true;                     
                        }
                    }
                }
                else
                {
                    sprintf(sendbuf, "登录失败，用户名或密码错误\n");
                    send(sockfd, sendbuf, strlen(sendbuf)+1, 0);
                    return false;
                }
            }
            else
            {
                sprintf(sendbuf, "登录失败，用户名或密码错误\n");
                send(sockfd, sendbuf, strlen(sendbuf)+1, 0);
                return false;
            }
        }
        else if(strcmp(user,"room") == 0)
        {
            if(strcmp(username,"create")== 0)
            {
                cout<<"进入房间"<<endl;
                //还没删除主线程的套接字
                waitroom::P1_add_room(sockfd);
            }
            else if(strcmp(username,"join")==0)
            {
                if(strcmp(useradmin,"player")==0)
                {
                    waitroom::P2_add_room(sockfd);
                }
                else if(strcmp(useradmin,"visited")==0)
                {
                    waitroom::observer_add_room(sockfd);
                }
            }
        }
        else if(strcmp(user,"player") == 0)
        {
            if(strcmp(username,"P1")==0)
            {
                
                if(strcmp(useradmin,"ready")==0)
                {   
                    cout<<"玩家1准备"<<endl;
                    waitroom::ready(sockfd);
                }
                else if(strcmp(useradmin,"unready")==0)
                {
                    cout<<"玩家2取消准备"<<endl;
                    waitroom::unready(sockfd);
                }
            }
            else if(strcmp(username,"P2")==0)
            {
                if(strcmp(useradmin,"ready")==0)
                {
                    waitroom::ready(sockfd);
                }
                else if(strcmp(useradmin,"unready")==0)
                {
                    waitroom::unready(sockfd);
                }
            }
        }
        else if(strcmp(user, "request") == 0)
        {
            cout << "请求" << endl;
            for(num = 0; num < 50; num++)
            {
                if(clientInfo[num].sockfd != 0)
                {
                    send(clientInfo[num].sockfd, recvbuf, strlen(recvbuf)+1, 0);
                    cout << recvbuf << endl;
                }
            }
        }
        else if(strcmp(user, "choise") == 0)
        {
            for(num = 0; num < 50; num++)
            {
                if(clientInfo[num].sockfd != 0)
                {
                    send(clientInfo[num].sockfd, recvbuf, strlen(recvbuf)+1, 0);
                    cout << recvbuf << endl;
                }
            }
        }


    }
    return true;
}
void new_wait_room() //创建线程开新房间类
{
    waitroom R1;
    R1.new_play_room();
}
class Server
{
private:
    int sockfd;//套接字描述符
    int bind_ret;//绑定返回值
    int listen_ret;//监听返回值
    int accept_fd;//接受连接返回值
    int epfd;
    int reval;
    char recvbuf[256];
    //定义结构体
    struct sockaddr_in addr;
    socklen_t len;
    //客户端地址
    // struct sockaddr_in clientaddr;
    // //客户端地址长度
    // socklen_t clientaddr_len = sizeof(clientaddr);
public:
    Server(){}
    ~Server(){}
    int InitServer()
    {
        //创建套接字(TCP通信,IPV4)
        sockfd =  socket(AF_INET, SOCK_STREAM, 0);
        if(sockfd < 0)
        {
            cerr << "创建套接字失败" << endl;
            return -1;
        }
        //每个字节都用0填充
        memset(&addr,0, sizeof(addr));
        //客户端地址长度
        len = sizeof(addr);
        //使用IPv4地址
        addr.sin_family = AF_INET;
        //端口号
        addr.sin_port = htons(PORT);
        //具体的IP地址
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        return sockfd;
    }

    void BindServer()
    {
        //绑定端口
        bind_ret = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
        if(bind_ret < 0)
        {
            cerr << "绑定端口失败" << endl;
            close(sockfd);
            return;
        }
    }

    void ListenServer()
    {
        //监听
        listen_ret = listen(sockfd, LISTEN_NUMBER);
        if(listen_ret < 0)
        {
            cerr << "监听失败" << endl;
            close(sockfd);
            return;
        }
    }

    void Epoll()
    {
        //epoll监控
        epfd = epoll_create(50);
        if(epfd < 0)
        {
            perror("epfd error");
        }

        //把监听套接字描述符添加到epoll监听队列
        struct epoll_event event;
        event.events = EPOLLIN;
        event.data.fd = sockfd;
        reval = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);
        if(reval < 0)
        {
            perror("ctl error");
        }

        //将标准输入加入监控
        event.events = EPOLLIN;
        event.data.fd = 0;
        reval = epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &event);
        if(reval < 0)
        {
            perror("ctl error");
        }
    }

    void user()
    {
        while(1)
        {
            //等待数据发生
            struct epoll_event reevent[50];
            int size = epoll_wait(epfd, reevent, 50, -1);
            if(size < 0)
            {
                perror("wait error");
                continue;
            }
            for(int num = 0; num < size; num++)
            {
                
                //客户端接入
                if(reevent[num].data.fd == sockfd)
                {
                    //接收
                    int connefd = accept(sockfd, (struct sockaddr *)(&addr), &len);
                    if(connefd < 0)
                    {
                        perror("accept error");
                    }

                    printf("客户端IP:%s\n", inet_ntoa(addr.sin_addr));

                    //将客户端加入监听
                    struct epoll_event event;
                    event.events = EPOLLIN;
                    event.data.fd = connefd;
                    reval = epoll_ctl(epfd, EPOLL_CTL_ADD, connefd, &event);
                    if(reval < 0)
                    {
                        perror("ctl_con error");
                    }
                    //send(connefd, "请输入用户名,格式：{join:XXX}\n", sizeof("请输入用户名,格式：{join:XXX}"), 0);

                }
                //客户端来数据
                else
                {
                    reval = recv(reevent[num].data.fd, recvbuf, sizeof(recvbuf), 0);
                    if(reval < 0)
                    {
                        perror("recv error");
                        close(reevent[num].data.fd);
                    }
                    else if(reval == 0)
                    {
                        cout << "客户端下线\n";
                        close(reevent[num].data.fd);
                    }
                        

                    else
                    {
                        cout<<recvbuf;
                        
                        // if(recvbuf[0]=='1')
                        // {
                        //     cout<<"进入房间"<<endl;
                        //     fdc = reevent[num].data.fd;
                        //     struct epoll_event event;
                        //     event.events = EPOLLIN;
                        //     event.data.fd = fdc;
                        //     int reval = epoll_ctl(epfd, EPOLL_CTL_DEL,fdc, &event);
                        //     if(reval < 0)
                        //     {
                        //         perror("ctl_con_del error");
                        //     }

                        //     waitroom::P1_add_room(fdc);
                        // }

                        // if(recvbuf[0]=='2')//比如协议是join:room_num
                        // {
                        //     cout<<"玩2进入房间"<<endl;
                        //     fdc = reevent[num].data.fd;
                        //     struct epoll_event event;
                        //     event.events = EPOLLIN;
                        //     event.data.fd = fdc;
                        //     int reval = epoll_ctl(epfd, EPOLL_CTL_DEL,fdc, &event);
                        //     if(reval < 0)
                        //     {
                        //         perror("ctl_con_del error");
                        //     }

                        //     waitroom::P2_add_room(fdc,1);

                        // }
                        message(reevent[num].data.fd, recvbuf);
                        bzero(recvbuf, sizeof(recvbuf));
                        
                        
                    }
                }
            }

        }
    }
    
    void CloseServer()
    {
        close(sockfd);
    }
};


void Stream()
{
    Server server;
    server.InitServer();
    server.BindServer();
    server.ListenServer();
    server.Epoll();
    server.user();
    server.CloseServer();
}

int main(void)
{
    read_file();
    thread t1(new_wait_room);
    thread t2(new_wait_room);
    thread t(Stream);
    t.join();
    t2.join();
    t1.join();
    return 0;
}